const { ccclass, property, menu } = cc._decorator;

@ccclass
@menu("自定义组件/ScrollView/TableView")
export default class TableView extends cc.Component {
    @property(cc.ScrollView)
    scrollview: cc.ScrollView = null;
    @property(cc.Prefab)
    itemPrefab: cc.Prefab = null;


    _node_pool: cc.NodePool = null;

    @property()
    perLoad: number = 7;
    
    @property({
        tooltip: "检测敏感度,像素值,移动多少个像素检测一次"
    })
    detectionThreshold: number = 1;

    _is_auto_add: boolean = false; // 是否动态加载
    content: cc.Node = null;
    item: cc.Node = null;
    layout: cc.Layout = null;

    _horizontal_interval: 0;   // 水平间隔
    _vertical_interval: 0;      // 垂直间隔
    _callback: any = null;//返回当前需要显示cell
    dataCount: 0;
    itemIsInit = false;
    lastMove: number = 0;
    _itemArray: cc.Node[];

    onLoad() {
        if (this.content) {
            return
        }

        this._node_pool = new cc.NodePool();
        this._itemArray = [];
        this.content = this.scrollview.content
        if (!this.itemPrefab) {
            this.item = this.content.children[0]
        }
        else {
            this.item = cc.instantiate(this.itemPrefab);
        }
        this.optimization(this.scrollview.node);
        this.optimization(this.scrollview.node.getChildByName("view"));
        this.optimization(this.content);
        this.setupWidget()
        this.setupLayout()
        this.hideAllItem()
        this.regissetScrollEvent()

    }
    onDestroy() {
        cc.log("节点池: nodePool ->", this._node_pool);
    }

    //优化操作;转移锚点到1 
    optimization(node) {
        if (node && node.anchorY == 0.5) {
            node.anchorY = 1;
            node.y = node.y + node.width;
        }
    }


    // 设置约束，
    setupWidget() {

        let widget = this.content.getComponent(cc.Widget)
        if (!widget) {
            return
        }

        widget.isAlignLeft = true
        widget.left = 0
        widget.isAlignTop = true
        widget.top = 0
        widget.isAlignBottom = false
        widget.isAlignRight = true
        widget.right = 0
    }

    // 设置布局
    setupLayout() {
        // 注销节点上的布局，方便后面手动排版
        this.layout = this.content.getComponent(cc.Layout)
        if (!this.layout) {
            this.layout = new cc.Layout();
            this.layout.paddingTop = 0;
            this.layout.paddingBottom = 0;
            this.layout.paddingLeft = 0;
            this.layout.paddingRight = 0;
            this.layout.spacingY = 0;
            return
        }
        this.layout.enabled = false
        this.layout.resizeMode = cc.Layout.ResizeMode.NONE
        this.content.anchorX = 0.5
        this.content.anchorY = 1
    }

    initAllItem(data_source_count) {

        if (!this.content) {
            this.onLoad()
        }



        let need_count = 0
        need_count = Math.ceil((this.content.parent.height - this.layout.paddingTop - this.layout.paddingBottom) / (this.item.height + this.layout.spacingY)) + this.perLoad;

        if (data_source_count < need_count) {
            this._is_auto_add = false
            need_count = data_source_count
        } else {
            this._is_auto_add = true
        }

        if (this.content.children.length < need_count) {
            let can_insert_count = need_count - this.content.children.length

            for (let index = 0; index < can_insert_count; index++) {
                let node = cc.instantiate(this.item)
                node.parent = this.content
            }
        }

    }

    hideAllItem(itemCount = 0) {

        if (!this.item) {

            //    cc.log("没有子节点数据!!")
            return;
        }

        let self = this
        this._itemArray.length = 0;
        this.content.children.forEach((item, index) => {
            item.zIndex = index;
            this._itemArray.push(item);
            if (index > itemCount - 1) {
                item.y = - self.layout.paddingTop - (item.height + self.layout.spacingY) * (index + 1) + item.height / 2 + self.layout.spacingY
                item.active = false
            }
        })
        this.content.height = 0
    }

    /**
     * 
     * @param dataCount 数据长度
     * @param callback 
     * @param itemIsInit 节点使用时是否执行了数据初始化
     */
    setDataAndReload(dataCount, callback: (node: cc.Node, index: number, isDynamic: boolean) => void, itemIsInit = false) {

        if (dataCount != 0) {
            this.initAllItem(dataCount)
        }

        this.hideAllItem()

        this._callback = callback
        this.dataCount = dataCount
        this.itemIsInit = itemIsInit
        // this.content.y = this.content.parent.height / 2
        if (dataCount == 0) {
            return
        }


        this.scrollview.stopAutoScroll()

        for (let index = 0; index < dataCount; index++) {
            if (callback && index < this.content.childrenCount) {
                let node = this.content.children[index]
                node.active = true;
                //node.ZIndex = index;
                callback(node, index, false)
            } else {
                break;
            }
        }


        this.content.height = dataCount * this.item.height + (dataCount - 1) * this.layout.spacingY + this.layout.paddingBottom + this.layout.paddingTop
        this.content.y = 0;
    }

    regissetScrollEvent() {

        this.lastMove = this.content.y
        let offset = this.detectionThreshold || 1 //每移动多少像素检测一次
        this.scrollview.node.on('scrolling', (event) => {
            if (this._is_auto_add) {
                // 动态加载
                let chazhi = this.lastMove - this.content.y
                if (chazhi > offset) {//下滑

                    // 计算最下面一个是否移出视图
                    let bottom = this.getBottomItem()
                    if (!bottom) return;
                    let pointy = cc.v2(0, bottom.y)
                    let a = this.content.convertToWorldSpaceAR(pointy)
                    let b = this.content.parent.convertToNodeSpaceAR(a)
                    if (b.y < -(this.content.parent.height + bottom.height / 2)) {
                        // cc.log("下滑")
                        let top = this.getTopItem()
                        let topZorder = top.zIndex;

                        if (topZorder <= 0) {
                            return
                        }
                        let order = topZorder - 1
                        //最下面的结点删掉
                        bottom = this._itemArray.pop();//
                        let node
                        //如果这个节点没有执行初始化,那么干掉这个重新创建一个新的
                        if (!this.itemIsInit) {
                            this._put(bottom)
                            //创建一个节点 放在最上面
                            node = this._getCanUsedItem();
                            node.parent = this.content;
                        } else {
                            node = bottom
                        }

                        node.y = top.y + this.layout.spacingY + node.height
                        node.zIndex = order;
                        this._itemArray.unshift(node);

                        if (this._callback) {
                            this._callback(node, order, true);
                        }

                    }
                    this.lastMove = this.content.y
                } else if (chazhi < -offset) {//上滑
                    // 计算最上面一个是否移出视图
                    let top = this.getTopItem()
                    if (!top) return;
                    let pointy = cc.v2(0, top.y)
                    //将节点坐标 转换到 view层进行比较
                    let a = this.content.convertToWorldSpaceAR(pointy)
                    let b = this.content.parent.convertToNodeSpaceAR(a)
                    if (b.y > top.height / 2) {
                        // cc.log("上移")
                        let bottom = this.getBottomItem()
                        let bottomOrder = bottom.zIndex;

                        if (bottomOrder >= this.dataCount - 1) {
                            return
                        }

                        //最上面的结点删掉
                        top = this._itemArray.shift()
                        let node
                        //如果这个节点没有执行初始化,那么干掉这个重新创建一个新的
                        if (!this.itemIsInit) {
                            this._put(top)
                            //创建一个节点 放在最上面
                            node = this._getCanUsedItem();
                            node.parent = this.content;
                        } else {
                            node = top
                        }
                        node.y = bottom.y - this.layout.spacingY - node.height
                        let order = bottomOrder + 1
                        node.zIndex = order;
                        this._itemArray.push(node);

                        if (this._callback) {
                            this._callback(node, order, true);
                        }
                    }
                    this.lastMove = this.content.y
                }

            }
        }, this)
    }

    getTopItem() {
        return this._itemArray[0];
    }

    getBottomItem() {
        return this._itemArray[this._itemArray.length - 1];
    }
    /**没有父节点的子节点 */
    _getCanUsedItem() {
        if (this._node_pool.size() > 0) {
            // cc.log("节点池 -> 取节点")
            return this._node_pool.get();
        } else {
            // cc.log("节点池 -> 生成节点")
            return cc.instantiate(this.itemPrefab);
        }
    }
    _put(node) {
        this._node_pool.put(node);
    }
}
